/*============================================================================
 PROJECT: CoreTextDemo
 FILE:    MarkupParser.m
 AUTHOR:  Khoai Nguyen
 DATE:    7/4/13
 =============================================================================*/

/*============================================================================
 IMPORT
 =============================================================================*/
#import "MarkupParser.h"

/*============================================================================
 PRIVATE MACRO
 =============================================================================*/
#define UIColorFromRGB(rgbValue)        [UIColor \
colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 \
green:((float)((rgbValue & 0xFF00) >> 8))/255.0 \
blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0]

/*============================================================================
 PRIVATE INTERFACE
 =============================================================================*/
@interface MarkupParser()
@property (nonatomic, strong) NSDictionary *attributes;
@end

@implementation MarkupParser

- (id)init {
    self = [super init];
    if (self) {
        self.font = [UIFont systemFontOfSize:[UIFont systemFontSize]];
        self.color = [UIColor whiteColor];
        self.strokeColor = [UIColor whiteColor];
        self.strokeWidth = 0;
    }
    return self;
}

+ (int)intValueWithHexaString:(NSString *)hexaString {
    unsigned int outVal;
    
    NSScanner* scanner = [NSScanner scannerWithString:hexaString];
    [scanner scanHexInt:&outVal];
    
    return outVal;
}

- (NSDictionary *)attributesWithFont:(UIFont *)font
                               color:(UIColor *)color
                         strokeColor:(UIColor *)strokeColor
                          strokeWith:(CGFloat)strokeWidth {
    
    CTFontRef fontRef = CTFontCreateWithName((__bridge CFStringRef)font.fontName, font.pointSize, NULL);
    NSDictionary *attributes = @{(id)kCTForegroundColorAttributeName: (id)color.CGColor,
                                 (id)kCTFontAttributeName: (id)CFBridgingRelease(fontRef),
                                 (NSString *)kCTStrokeColorAttributeName: (id)strokeColor.CGColor,
                                 (NSString *)kCTStrokeWidthAttributeName: (id)@(strokeWidth)};
    return attributes;
}

- (void)resetStyle {
    if(self.color && self.font && self.strokeColor) {
        self.attributes = [self attributesWithFont:self.font
                                             color:self.color
                                       strokeColor:self.strokeColor
                                        strokeWith:self.strokeWidth];
    }
}

- (NSMutableAttributedString *)attrStringFromMarkup:(NSString *)html {
    
    /* break out all html tags */
    NSMutableAttributedString *aString = [[NSMutableAttributedString alloc] initWithString:@""];
    
    if(html.length > 0) {
        NSRegularExpression *regex = [[NSRegularExpression alloc]
                                      initWithPattern:@"(.*?)(<[^>]+>|\\Z)"
                                      options:NSRegularExpressionCaseInsensitive|NSRegularExpressionDotMatchesLineSeparators
                                      error:nil];
        
        NSArray *chunks = [regex matchesInString:html
                                         options:0
                                           range:NSMakeRange(0, [html length])];
        
        
        /* default font, color, stroke color */
        __block UIFont *font = self.font;
        __block UIColor *color = self.color;
        __block UIColor *strokeColor = self.strokeColor;
        __block CGFloat strokeWidth = self.strokeWidth;
        
        /* reset style */
        [self resetStyle];
        
        for (NSTextCheckingResult *b in chunks) {
            
            /* get parts from chunk */
            NSArray *parts = [[html substringWithRange:b.range] componentsSeparatedByString:@"<"];
            
            /* apply the current text style */
            NSString *stringValue = parts[0];
            [aString appendAttributedString:[[NSAttributedString alloc] initWithString:stringValue attributes:self.attributes]];
            
            /* reset style */
            [self resetStyle];
            
            /* get new style */
            if ([parts count] > 1) {
                NSString *tag = (NSString *)parts[1];
                if ([tag hasPrefix:@"font"]) {
                    //stroke color
                    NSRegularExpression *scolorRegex = [[NSRegularExpression alloc] initWithPattern:@"(?<=strokeColor=\")\\w+" options:0 error:NULL];
                    
                    [scolorRegex enumerateMatchesInString:tag options:0 range:NSMakeRange(0, [tag length]) usingBlock:^(NSTextCheckingResult *match, NSMatchingFlags flags, BOOL *stop){
                        if ([[tag substringWithRange:match.range] isEqualToString:@"none"]) {
                            strokeWidth = 0.0;
                        } else {
                            strokeWidth = -3.0;
                            strokeColor = UIColorFromRGB([MarkupParser intValueWithHexaString:[tag substringWithRange:match.range]]);
                        }
                    }];
                    
                    //color
                    NSRegularExpression* colorRegex = [[NSRegularExpression alloc] initWithPattern:@"(?<=color=\")\\w+" options:0 error:NULL];
                    [colorRegex enumerateMatchesInString:tag options:0 range:NSMakeRange(0, [tag length]) usingBlock:^(NSTextCheckingResult *match, NSMatchingFlags flags, BOOL *stop) {
                        color = UIColorFromRGB([MarkupParser intValueWithHexaString:[tag substringWithRange:match.range]]);
                    }];
                    
                    //face
                    NSRegularExpression* faceRegex = [[NSRegularExpression alloc] initWithPattern:@"(?<=face=\")[^\"]+" options:0 error:NULL];
                    [faceRegex enumerateMatchesInString:tag options:0 range:NSMakeRange(0, [tag length]) usingBlock:^(NSTextCheckingResult *match, NSMatchingFlags flags, BOOL *stop){
                        font = [UIFont fontWithName:[tag substringWithRange:match.range] size:font.pointSize];
                    }];
                    
                    // size
                    NSRegularExpression* sizeRegex = [[NSRegularExpression alloc] initWithPattern:@"(?<=size=\")[^\"]+" options:0 error:NULL];
                    [sizeRegex enumerateMatchesInString:tag options:0 range:NSMakeRange(0, [tag length]) usingBlock:^(NSTextCheckingResult *match, NSMatchingFlags flags, BOOL *stop) {
                        font = [UIFont fontWithName:font.familyName size:[tag substringWithRange:match.range].intValue];
                    }];
                    
                    self.attributes = [self attributesWithFont:font
                                                         color:color
                                                   strokeColor:strokeColor
                                                    strokeWith:strokeWidth];
                } //end of font parsing
            }
        }
    }
    return aString;
}

@end
